using System;
using System.Runtime.InteropServices;
using System.IO;
using System.Text;

namespace OpenNETCF.Compression
{   
    public class GZStream : GZBaseStream
    {
        private bool forReading;

        internal GZStream(Stream baseStream, CompressionLevel level, CompressionStrategy strategy, bool forReading)
            : base(baseStream)
        {
            this.forReading = forReading;
            this.gzstream = GZOpen(baseStream, level, strategy, forReading);
        }

        public static GZStream OpenRead(Stream baseStream)
        {
            return new GZStream(baseStream, CompressionLevel.Default, CompressionStrategy.Default, true);
        }

        public static GZStream OpenWrite(Stream baseStream, CompressionLevel level, CompressionStrategy strategy)
        {
            return new GZStream(baseStream, level, strategy, false);
        }

        public static GZStream OpenWrite(Stream baseStream, CompressionLevel level)
        {
            return OpenWrite(baseStream, level, CompressionStrategy.Default);
        }

        public static GZStream OpenWrite(Stream baseStream)
        {
            return OpenWrite(baseStream, CompressionLevel.Default, CompressionStrategy.Default);
        }

        public override bool CanWrite
        {
            get { return !forReading; }
        }

        public override bool CanRead
        {
            get { return forReading; }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            if (!CanRead)
                throw new InvalidOperationException("Not open for reading");
            return gzread(ref gzstream, buffer, offset, count);
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            if (!CanWrite)
                throw new InvalidOperationException("Not open for writing");
            gzwrite(ref gzstream, buffer, offset, count);
        }

        public override void Flush()
        {
            gzflush(ref gzstream, zlib_native.Z_SYNC_FLUSH);
        }

        public override void Close()
        {
            if ( !forReading )
                Flush();
            base.Close();
        }
    }
}

